home *** CD-ROM | disk | FTP | other *** search
- /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1984. */
- static char rcsid[] = "$Header: eval.c,v 2.3 84/07/19 11:47:18 guido Exp $";
-
- /*
- * B editor -- Width attribute evaluation.
- */
-
- #include "b.h"
- #include "node.h"
- #include "gram.h"
- #include "eval.h"
-
-
- /*
- * The following convention is used throughout the editor to indicate
- * the sizes of objects.
- * - A zero or positive `width' value means the object contains no
- * linefeeds. The width is counted in characters.
- * - A negative `width' means the object (or its children) contains
- * at leasty one linefeed (return is treated as a linefeed here).
- * The number of linefeeds is -width.
- * There is no indication whether the object fits on that number of
- * physical lines, as logical lines may have arbitrary length.
- *
- * For coordinates the following convention is used.
- * (Note that, in accordance to the convention in curses(3), the
- * `y' coordinate always precedes the `x' coorxdinate.)
- * - `Y' is the line number, counted from the beginning of the unit.
- * These are logical lines rather than physical lines.
- * The first line has line number 0.
- * - `X' is the column number. The first column is 0. For x < 0,
- * see the important notice below.
- * - `Level' is the indentation level, indicating where a new line
- * would start if inserted at the current position.
- * The initial `x' position of such a line is `level*TABS'.
- *
- * ***** IMPORTANT NOTICE *****
- * A special case is x = -1. This means that the current x position is
- * unknown. Further output on the same line is suppressed, until a
- * linefeed is encountered. This feature is necessary because while
- * calculating coordinates, when an object has width < 0, only the y
- * coordinate of the end of that object is known. In this case, the
- * next non-empty object MUST START WITH A LINEFEED, or it will not
- * be visible on the screen (in practice, a space is sometimes present
- * in the parse tree which is not shown then).
- */
-
-
- /*
- * Compute the (y, x) coordinates and indent level just before
- * the beginning of the j'th child, if the current node starts
- * at the initial values of (y, x) and level.
- */
-
- Visible Procedure
- evalcoord(n, jch, py, px, plevel)
- register node n;
- register int jch;
- int *py;
- int *px;
- int *plevel;
- {
- node nn;
- register int i;
- register string *rp = noderepr(n);
- register int k;
- register int y = 0;
- int x = *px;
- int level = *plevel;
- int nch = Type(n) == Tex ? 0 : nchildren(n);
-
- if (jch > nch)
- jch = nch+1;
- for (i = 0; i < jch; ++i) {
- if (i) {
- nn = child(n, i);
- k = width(nn);
- if (k < 0) {
- y += -k;
- x = k;
- }
- else if (x >= 0)
- x += k;
- }
- k = Fwidth(rp[i]);
- if (k < 0) {
- y += -k;
- x = rp[i][0] == '\r' ? 0 : TABS*level;
- x += strlen(rp[i]) - 1;
- }
- else {
- if (x >= 0)
- x += k;
- if (rp[i]) {
- if (rp[i][k] == '\t')
- ++level;
- else if (rp[i][k] == '\b')
- --level;
- }
- }
- }
-
- *py += y;
- *px = x;
- *plevel = level;
- }
-
-
- /*
- * Yield the width of a piece of fixed text as found in a node's repr,
- * excluding \b or \t. If \n or \r is found, -1 is returned.
- * It assumes that \n or \r only occur as first
- * character, and \b or \t only as last.
- */
-
- Visible int
- fwidth(str)
- register string str;
- {
- register int c;
- register int n = 0;
-
- if (!str)
- return 0;
- c = str[0];
- if (c == '\r' || c == '\n')
- return -1;
- for (; c; c = *++str)
- ++n;
- if (n > 0) {
- c = str[-1];
- if (c == '\t' || c == '\b')
- --n;
- }
- return n;
- }
-
-
- /*
- * Evaluate the width of node n, assuming the widths of its children
- * have correctly been calculated.
- */
-
- Visible int
- evalwidth(n)
- register node n;
- {
- register int w;
- register int i;
- register string *rp;
- register int y = 0;
- register int x = 0;
- register int nch;
- register node nn;
-
- rp = noderepr(n);
- nch = Type(n) == Tex ? 0 : nchildren(n);
- for (i = 0; i <= nch; ++i) {
- if (i) {
- nn = child(n, i);
- w = width(nn);
- if (w < 0) {
- y += -w;
- x = w;
- }
- else
- x += w;
- }
- w = Fwidth(rp[i]);
- if (w < 0) {
- y += -w;
- x = 0;
- }
- else
- x += w;
- }
- if (y > 0)
- return -y;
- return x;
- }
-